
//MAX30102采用的是软件IIC
#include <stddef.h>
#include <stdio.h>
#include "ohos_types.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "iot_i2c.h"
#include "iot_gpio_ex.h"
//#include "max30102_func.h"
#include "oled_ssd1306.h"
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_task.h"
#include "myiic.h"
#include "hi_i2c.h"


#define BAUDRATE (400 * 1000)
#define I2C_ID 0
#define MPU_I2C_IDX 0

#define MAX_BRIGHTNESS 255

#define max30102_I2C_BAUDRATE (115200) // 波特第

#define DELAY_100_MS (100 * 1000)
#define input_pin 5

unsigned int MAX30102_INT;
unsigned int *input_ptr=&MAX30102_INT;


u8 max30102_Bus_Write(u8 Register_Address, u8 Word_Data);
u8 max30102_Bus_Read (u8 Register_Address);


uint32_t aun_ir_buffer[500]; //IR LED sensor data
int32_t n_ir_buffer_length;    //data length
uint32_t aun_red_buffer[500];    //Red LED sensor data
int32_t n_sp02; //SPO2 value
int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
int32_t n_heart_rate;   //heart rate value
int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
uint8_t uch_dummy;
uint32_t un_min, un_max, un_prev_data;  
int i;
int32_t n_brightness;
float f_temp;
u8 temp_num=0;
u8 temp[6]={1,2,3,4,5,6};
u8 str[100];
u8 dis_hr=0,dis_spo2=0;


typedef struct {
    /** Pointer to the buffer storing data to send */
    unsigned char *sendBuf;
    /** Length of data to send */
    unsigned int  sendLen;
    /** Pointer to the buffer for storing data to receive */
    unsigned char *receiveBuf;
    /** Length of data received */
    unsigned int  receiveLen;
} IotI2cData;

/**
 * @brief Send Write address to MPU device.
 * @param regAddr the register address to Read or Writen.
 * @return Returns{@link IOT_SUCCESS} if the operation is successful;
 *  returns an error code defined in {@link iot_errno.h} otherwise.
 * */ 
uint8_t SendAddress(uint8_t regAddr)
{ 
    unsigned int id = I2C_ID;
    uint8_t buffer[] = {regAddr};
    IotI2cData i2cData;
	i2cData.receiveBuf = NULL;
    i2cData.receiveLen = 0;
    i2cData.sendBuf = buffer;
    i2cData.sendLen = sizeof(buffer)/sizeof(buffer[0]);
    return IoTI2cWrite(id, max30102_WR_address|I2C_WR,i2cData.sendBuf, i2cData.sendLen);  //==发送器件地址+写命第 + 寄存器regAddr 
}

uint8_t MPU_Cmd(uint8_t regAddr)
{ 
	hi_i2c_idx id = MPU_I2C_IDX;
    uint8_t buffer[] = {regAddr};
    hi_i2c_data i2cData;
	i2cData.receive_buf = NULL;
    i2cData.receive_len = 0;
    i2cData.send_buf = buffer;
    i2cData.send_len = sizeof(buffer)/sizeof(buffer[0]);
    return hi_i2c_write((hi_i2c_idx)id, (max30102_WR_address|I2C_WR), &i2cData);  //==发送器件地址+写命第 + 寄存器regAddr 
}

static uint32_t I2cWiteByte(uint8_t regAddr, uint8_t byte)
{
    printf("in the I2cWiteByte\n");
    unsigned int id = I2C_ID;
    uint8_t buffer[] = {regAddr, byte};
    IotI2cData i2cData = {0};
    i2cData.sendBuf = buffer;
    i2cData.sendLen = sizeof(buffer) / sizeof(buffer[0]);
    return IoTI2cWrite(id, max30102_WR_address|I2C_WR, i2cData.sendBuf, i2cData.sendLen);

    //max30102_Bus_W rite(regAddr,byte);
    return 0;
}

uint32_t MPU_Write_Data(uint8_t regAddr, uint8_t *data)
{
    hi_i2c_idx id = MPU_I2C_IDX;
    uint8_t buffer[] = {regAddr, data};
    hi_i2c_data i2cData;
	i2cData.receive_buf = NULL;
    i2cData.receive_len = 0;
    i2cData.send_buf = buffer;
    i2cData.send_len = sizeof(buffer)/sizeof(buffer[0]);
    return hi_i2c_write((hi_i2c_idx)id, (max30102_WR_address|I2C_WR), &i2cData);  
}

uint32_t MPU_Read_Data(uint8_t regAddr, uint8_t *data, unsigned int dataLen)
{
    hi_i2c_idx id = MPU_I2C_IDX;
    hi_i2c_data i2cData;
    i2cData.send_buf = NULL;
    i2cData.send_len = 0;
    i2cData.receive_buf = data;
    i2cData.receive_len = dataLen;
	MPU_Cmd(regAddr);
    return hi_i2c_read((hi_i2c_idx)id,(max30102_WR_address|I2C_RD), &i2cData);
}
static uint32_t I2cReadByte(uint8_t regAddr, uint8_t *data,uint8_t len)
{
   // printf("in the I2cReadByte\n");
    unsigned int id = I2C_ID;
    //uint8_t buffer2[] = {regAddr, byte};
    IotI2cData i2cData2 = {0};
	//uint8_t *byte_ptr=&byte;
    i2cData2.sendBuf = NULL;
    i2cData2.sendLen = 0;
    i2cData2.receiveBuf = data;
    i2cData2.receiveLen = len;
    SendAddress(regAddr);
    //return hi_i2c_read(id, max30102_WR_address|I2C_RD, &i2cData2);
    return IoTI2cRead(id, max30102_WR_address|I2C_RD, i2cData2.receiveBuf, i2cData2.receiveLen);
}

/**
 * @brief Max30102  Initialize.
 */
void Max30102Init(void)
{
    //IIC_Init
    IoTGpioInit(13); 
    IoSetFunc(13, 6); /* gpio13使用6功能 */
    IoTGpioInit(14); /* 初始化gpio14 */
    IoSetFunc(14, 6); /* gpio14使用6功能 */
    IoTGpioInit(5); /* 初始化gpio5 */
    IoSetFunc(5, 0); 
    IoTGpioSetDir(5, 0);//设置输入
    IoTI2cInit(0, BAUDRATE);
    
    max30102_reset();
   // uint32_t status;
    //I2cWiteByte(REG_INTR_ENABLE_1,0xc0);	// INTR setting
	//I2cWiteByte(REG_INTR_ENABLE_2,0x00);
	//I2cWiteByte(REG_FIFO_WR_PTR,  0x00);  	//FIFO_WR_PTR[4:0]
	//I2cWiteByte(REG_OVF_COUNTER,  0x00);  	//OVF_COUNTER[4:0]
	//I2cWiteByte(REG_FIFO_RD_PTR,  0x00);  	//FIFO_RD_PTR[4:0]

	//I2cWiteByte(REG_FIFO_CONFIG,  0x0f);  	//sample avg = 1, fifo rollover=false, fifo almost full = 17
	//I2cWiteByte(REG_MODE_CONFIG,  0x03);  	//0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
	//I2cWiteByte(REG_SPO2_CONFIG,  0x27);  	// SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)  
	//I2cWiteByte(REG_LED1_PA,	  0x24);   	//Choose value for ~ 7mA for LED1
	//I2cWiteByte(REG_LED2_PA,	  0x24);   	// Choose value for ~ 7mA for LED2
	//I2cWiteByte(REG_PILOT_PA,	  0x7f);   	// Choose value for ~ 25mA for Pilot LED
    
    MPU_Write_Data(REG_INTR_ENABLE_1,0xc0);	// INTR setting
	MPU_Write_Data(REG_INTR_ENABLE_2,0x00);
	MPU_Write_Data(REG_FIFO_WR_PTR,  0x00);  	//FIFO_WR_PTR[4:0]
	MPU_Write_Data(REG_OVF_COUNTER,  0x00);  	//OVF_COUNTER[4:0]
	MPU_Write_Data(REG_FIFO_RD_PTR,  0x00);  	//FIFO_RD_PTR[4:0
	MPU_Write_Data(REG_FIFO_CONFIG,  0x0f);  	//sample avg = 1, fifo rollover=false, fifo almost full = 17
	MPU_Write_Data(REG_MODE_CONFIG,  0x03);  	//0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
	MPU_Write_Data(REG_SPO2_CONFIG,  0x27);  	// SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)  
	MPU_Write_Data(REG_LED1_PA,	  0x24);   	//Choose value for ~ 7mA for LED1
	MPU_Write_Data(REG_LED2_PA,	  0x24);   	// Choose value for ~ 7mA for LED2
	MPU_Write_Data(REG_PILOT_PA,	  0x7f);   	// Choose value for ~ 25mA for Pilot LED
    
    //if (status != IOT_SUCCESS)
    // {
    //        return status;
    //    }
//    IoTI2cInit(1, max30102_I2C_BAUDRATE);
  //  for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++) {
  //      uint32_t status = WriteCmd(initCmds[i]);

    printf("\r\n MAX30102  init  successful\r\n");
 //   return IOT_SUCCESS;
}

void max30102_reset(void)
{
	MPU_Write_Data(REG_MODE_CONFIG,0x40);
	MPU_Write_Data(REG_MODE_CONFIG,0x40);
}

//detection rang of data 
void Dete_signalRang(void)
{
    un_min=0x3FFFF;
    un_max=0;
    printf("determine the signal range\n");

    int n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
	//read the first 500 samples, and determine the signal range
    
    for(i=0;i<n_ir_buffer_length;i++)
    {
        IoTGpioGetInputVal(input_pin,input_ptr);
    //  printf("MAX30102_INT=%d\n",MAX30102_INT);
        while(MAX30102_INT==1);   //wait until the interrupt pin asserts
        
		max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
		aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
		aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
            
        if(un_min>aun_red_buffer[i])
            un_min=aun_red_buffer[i];    //update signal min
        if(un_max<aun_red_buffer[i])
            un_max=aun_red_buffer[i];    //update signal max
    }
	un_prev_data=aun_red_buffer[i];
	//calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 

}

//measurn the SP02 and HR
void start_measure(void)
{
	while(1)
	{
        printf("in the loop\n");
		i=0;
        un_min=0x3FFFF;
        un_max=0;
		
		//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
        for(i=100;i<500;i++)
        {
            aun_red_buffer[i-100]=aun_red_buffer[i];
            aun_ir_buffer[i-100]=aun_ir_buffer[i];
               
            //update the signal min and max
            if(un_min>aun_red_buffer[i])
            un_min=aun_red_buffer[i];
            if(un_max<aun_red_buffer[i])
            un_max=aun_red_buffer[i];
        }
		//take 100 sets of samples before calculating the heart rate.
        for(i=400;i<500;i++)
        {
           // printf("in the make data loop begin\n");
            un_prev_data=aun_red_buffer[i-1];
            while(MAX30102_INT==1);
            max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
            printf("temp[1]=%d,temp[2]=%d,temp[3]=%d,temp[4]=%d,temp[5]=%d,temp[6]=%d\n",*temp,*(temp+1),*(temp+2),*(temp+3),*(temp+4),*(temp+5));

			aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
			aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
        
            if(aun_red_buffer[i]>un_prev_data)
            {
                f_temp=aun_red_buffer[i]-un_prev_data;
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness-=(int)f_temp;
                if(n_brightness<0)
                    n_brightness=0;
            }
            else
            {
                f_temp=un_prev_data-aun_red_buffer[i];
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness+=(int)f_temp;
                if(n_brightness>MAX_BRIGHTNESS)
                    n_brightness=MAX_BRIGHTNESS;
            }
			//send samples and calculation result to terminal program through UART
			if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
			{
				dis_hr = n_heart_rate;
				dis_spo2 = n_sp02;
			}
			else
			{
				dis_hr = 0;
				dis_spo2 = 0;
			}
				printf("HR=%i, ", n_heart_rate); 
				printf("HRvalid=%i, ", ch_hr_valid);
				printf("SpO2=%i, ", n_sp02);
				printf("SPO2Valid=%i\r\n", ch_spo2_valid);
                msleep(10);
            //printf("in the make data loop end\n");
            //printf("\n");

		} 
        maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
      
    }	
}


void max30102_FIFO_ReadBytes(u8 Register_Address,u8* Data)
{	
   // printf("in the max30102_FIFO_ReadBytes \n");

	max30102_Bus_Read(REG_INTR_STATUS_1);
	max30102_Bus_Read(REG_INTR_STATUS_2);

	  	
    MPU_Read_Data(Register_Address, Data,6);  //连续读六字节数据?  

}

u8 max30102_Bus_Write(u8 Register_Address, u8 Word_Data)
{


	/* 第1步：发起I2C总线 */
	IIC_Start();

	/* 第2步：发起控制字节，高7bit地址，bit0读写控制位，0表示写，1表示读 */
	IIC_Send_Byte(max30102_WR_address | I2C_WR);	

	/* 第3步：发送ACK */
	if (IIC_Wait_Ack() != 0)
	{
		goto cmd_fail;	/* EEPROM器件无响应 */
	}

	/* 第4步：发送字节地址 */
	IIC_Send_Byte(Register_Address);
	if (IIC_Wait_Ack() != 0)
	{
		goto cmd_fail;	/
	}
	
	/* 第5步：开始写入数 */
	IIC_Send_Byte(Word_Data);

	/* 第6步：发送ACK */
	if (IIC_Wait_Ack() != 0)
	{
		goto cmd_fail;	/* EEPROM器件无响应 */
	}

	/* 发送I2C总线停止信号 */
	IIC_Stop();
	return 1;	

cmd_fail: 
	/* 发送I2C总线停止信号 */
	IIC_Stop();
	return 0;
}

u8 max30102_Bus_Read(u8 Register_Address)
{
	u8  data;
    u8 *data_ptr=&data;
MPU_Read_Data(Register_Address,data_ptr,1);
	return data;
}